package modes

import (
	"fmt"
	"strings"
)

/*
 * 描述: 录播课次表(new)
 *
 *****************************/

type PlayClass struct {
	Id         int64      `json:"play_id" xorm:"id"`                 // id
	PPId       int64      `json:"play_pid" xorm:"pid"`               // 项目id
	SSId       int64      `json:"play_sid" xorm:"sid"`               // 课程id
	Instructor string     `json:"play_instructor" xorm:"instructor"` // 授课老师
	VideoId    string     `json:"play_replay_id" xorm:"video_id"`    // 视频Id
	Duration   int32      `json:"play_duration" xorm:"duration"`     // 回放视频的时长(秒)
	Audition   int32      `json:"play_audition" xorm:"audition"`     // 试听类型(1-非试听, 2-试听)
	At         int64      `json:"play_at" xorm:"at"`                 // 创建结束
	Sort       int32      `json:"play_sort" xorm:"sort"`             // 排序( 程序步进值:100)
	Name       string     `json:"play_name" xorm:"name"`             // 课次名称
	Rect       []RecordAt `json:"rect" xorm:"-"`                     // 该课次最后最后一次播放进度
	IsColl     int        `json:"is_coll" xorm:"-"`                  // 是否已收藏 1已收藏 2未收藏
}

func (this *PlayClass) TableName() string {
	return "playclass"
}
func (this *PlayClass) Load() (bool, error) {
	return Db(0).Get(this)
}
func (this *PlayClass) Create() (int64, error) {
	return Db(0).Insert(this)
}
func (this *PlayClass) Update(id int64, columns ...string) (int64, error) {
	return Db(0).ID(id).MustCols(columns...).Update(this)
}
func (this *PlayClass) Delete(id int64) (int64, error) {
	return Db(0).ID(id).Delete(&PlayClass{})
}
func (this *PlayClass) Orders() map[string]string {
	return map[string]string{}
}

type AuditionCTime struct {
	Id        int64 `json:"s_id" xorm:"id"`
	Subjects  `json:"sje" xorm:"extends"`
	PlayClass `json:"py" xorm:"extends"`
}

func (this *AuditionCTime) KcIdList(val *Pager) error {
	list := make([]AuditionCTime, 0)
	val.TName = "subject"
	val.Page--
	if val.Page <= 0 {
		val.Page = 0
	}
	var field, sort, paixu string
	if this.Id == 0 {
		field = fmt.Sprintf("%s.id %% 100000 = 0  and playclass.audition = 2 and %s.start = 0", val.TName, val.TName)
	} else if (this.Id % 10000) == 0 {
		field = fmt.Sprintf("%s.id > %d and %s.id < %d  and playclass.audition = 2 and %s.start = 0", val.TName, this.Id, val.TName, this.Id+10000, val.TName)
	} else {
		field = fmt.Sprintf("%s.id > %d and %s.id < %d  and playclass.audition = 2 and %s.start = 0", val.TName, this.Id, val.TName, this.Id+100000, val.TName)
	}
	val.Total, _ = Db(1).Table(val.TName).
		Join("INNER", "playclass", fmt.Sprintf("%s.id = playclass.sid", val.TName)).
		Where(field).
		Where(val.ToWhere()).
		Count()

	paixu = fmt.Sprintf("%s.id", val.TName) // 默认ID

	if 1 == val.Rules {
		sort = fmt.Sprintf("%s desc", paixu)
	} else {
		sort = fmt.Sprintf("%s asc", paixu)

	}
	err := Db(1).Table(val.TName).
		Join("LEFT", "playclass", fmt.Sprintf("%s.id = playclass.sid", val.TName)).
		Where(field).
		Where(val.ToWhere()).
		OrderBy(sort).
		Limit(val.Count, val.Page*val.Count).
		Find(&list)
	if err == nil {
		val.List = list
	}
	return err
}

type JoinCourseSub struct {
	Subjects `xorm:"extends"`
	Coun     int64  `json:"count" xorm:"-"`
	TNames   string `json:"tNames" xorm:"-"`
}

func (this *JoinCourseSub) CLists(phone int64, uid int64, sid int64, val *Pager) error {
	class := Class{}
	cIdList, _ := class.GetCIdListByPhone(phone)
	kcBean := SubClass{}
	kcIdList, _ := kcBean.GetidsByCids(cIdList)

	list := make([]JoinCourseSub, 0)
	val.TName = "subject"
	val.Page--
	if val.Page <= 0 {
		val.Page = 0
	}
	var field, sort string
	field = fmt.Sprintf("typ asc,id") // 默认时间排序
	if 1 == val.Rules {
		sort = fmt.Sprintf("%s desc", field)
	} else {
		sort = fmt.Sprintf("%s asc", field)
	}
	//swhere := fmt.Sprintf("start = 0")
	val.Total, _ = Db(0).Table(val.TName).
		Where(val.ToWhere()).
		//Where(swhere).
		Where("id%1000 =0 and start = 0").
		Count()
	err := Db(0).Table(val.TName).
		Where(val.ToWhere()).
		//Where(swhere).
		Where("id%1000 =0 and start = 0").
		OrderBy(sort).
		Limit(val.Count, val.Page*val.Count).
		Find(&list)

	hasKclist := make([]JoinCourseSub, 0)

	for j, _ := range list {
		for _, haskcIdf := range kcIdList {
			if haskcIdf == list[j].Id {
				hasKclist = append(hasKclist, list[j])
			}

		}

	}
	list = hasKclist

	if err == nil {
		val.List = list // 课程Id
	}
	//构造 录播slice
	plays := []int64{}
	//构造 直播slice
	lives := []int64{}
	for n, _ := range list {
		if list[n].Subjects.Type == 1 {
			plays = append(plays, list[n].Subjects.Id)
		} else {
			lives = append(lives, list[n].Subjects.Id)
		}
	}
	//处理录播 plays
	plys, _ := (&PlayCountName{}).PlayClassCount(plays) //科目下课次 ids   1.取出录播课程下课次数量
	livs, _ := (&LiveCountName{}).LiveClassCount(lives) //科目下课次 ids   1.取出录播课程下课次数量
	plyss, _ := (&PlayTName{}).PlayClsTName(plays)      //科目下课次 ids   2 该录播课次下前三名老师名字
	livss, _ := (&LiveTName{}).LiveClsTName(lives)      //科目下课次 ids   2 该直播课次下前三名老师名字

	for _, it := range plys { //科目下课次 ids   1.取出录播课程下课次数量
		for n, _ := range list {
			if list[n].Id == it.Id {
				list[n].Coun = it.Count
			}
		}
	}

	for _, itt := range livs { //科目下课次 ids   1.取出录播课程下课次数量
		for n, _ := range list {
			if list[n].Id == itt.Id {
				list[n].Coun = itt.Count
			}
		}
	}

	for _, its := range plyss { //科目下课次 ids    2 该录播课次下前三名老师名字
		for n, _ := range list {
			if list[n].Id == its.Id {
				list[n].TNames = its.Tname
			}
		}
	}

	for _, itts := range livss { //科目下课次 ids   2 该直播课次下前三名老师名字
		for n, _ := range list {
			if list[n].Id == itts.Id {
				list[n].TNames = itts.Tname
			}
		}
	}

	//for n, _ := range list {
	//	var c int64
	//	var ss []string
	//	var err error
	//
	//	if list[n].Subjects.Type == 1 {
	//		c, ss, err = (&PlayClass{}).PlayClassCount(list[n].Subjects.Id)
	//	} else if list[n].Subjects.Type == 2 {
	//		c, ss, err = (&NewLiveClass{}).LiveClassCount(list[n].Subjects.Id)
	//	}
	//	if err != nil {
	//		return err
	//	}
	//	list[n].Coun = c
	//	list[n].TNames = ss
	//}
	return err
}

type PlayCountName struct {
	Id    int64 `xorm:"sid"`     // s_id 	课程id
	Count int64 `xorm:"s_count"` // count 课次数量
}

func (this *PlayCountName) PlayClassCount(sid []int64) ([]PlayCountName, error) {
	list := make([]PlayCountName, 0)
	err := Db(0).Table("playclass").Select("sid,COUNT(*) as s_count").In("sid", sid).GroupBy("sid").Find(&list)
	return list, err
}

type PlayTName struct {
	Id    int64  `xorm:"sid"`    //科目id
	Tname string `xorm:"t_name"` //名称
}

func (this *PlayTName) PlayClsTName(ids []int64) ([]PlayTName, error) {
	list := make([]PlayTName, 0)
	err := Db(0).SQL(fmt.Sprintf("SELECT DISTINCT sid,GROUP_CONCAT(DISTINCT instructor) as t_name from playclass where sid in (%v) GROUP BY sid", strings.Replace(strings.Trim(fmt.Sprint(ids), "[]"), " ", ",", -1))).Find(&list)
	return list, err

}

func (this *PlayClass) PlayClassCount(sid int64) (int64, []string, error) {
	swhere := fmt.Sprintf("sid  = %d ", sid)
	cou, _ := Db(0).Where(swhere).Count(this)
	list, err := this.PlayClassName(sid)
	return cou, list, err
}
func (this *PlayClass) PlayClassName(sid int64) ([]string, error) {
	swhere := fmt.Sprintf("sid  = %d ", sid)
	dl := []string{}
	return dl, Db(0).Table("playclass").Cols("instructor").Where(swhere).Limit(3).Find(&dl)
}

type PlaySubj struct {
	PlayClass `xorm:"extends"`
	Subjects  `xorm:"extends"`
}

// 录播课次
func (this *PlayClass) Lookups(uid, sid int64, val *Pager) error {
	list := make([]PlaySubj, 0)
	val.TName = "playclass"
	val.Page--
	var field, sort string
	switch val.Coll {
	case 0:
		field = fmt.Sprintf("%s.sort", val.TName) // 排序
	default:
		field = fmt.Sprintf("%s.sort", val.TName) // 排序
	}
	if 1 == val.Rules {
		sort = fmt.Sprintf("%s asc", field)
	} else {
		sort = fmt.Sprintf("%s desc", field)
	}
	swhere := fmt.Sprintf("sid = %d", sid)
	val.Total, _ = Db(0).Table(val.TName).Where(swhere).Count(this)
	err := Db(0).Table(val.TName).
		Join("LEFT", "subject", fmt.Sprintf("%s.sid = subject.id", val.TName)).
		Where(swhere).
		OrderBy(sort).
		Limit(val.Count, val.Page*val.Count).
		Find(&list)

	collen := Collen{
		UId: uid,
	}
	collenList, err := collen.ListByUid()

	// 提取课次Ids
	scIds := make([]int64, 0, len(list))
	mapps := map[int64]*PlayClass{}

	for n, _ := range list { // 效率高（遍历的是地址）
		scIds = append(scIds, list[n].PlayClass.Id)
		mapps[list[n].PlayClass.Id] = &list[n].PlayClass
		// for _, it := range list { // 效率低（遍历地址的同时还要构造N个临时对象赋值）（很多场景也用这种写法，对象是mini的，存的是指针）
		// scIds = append(scIds,it.Id)
	}
	rects:=[]RecordAt{}
	for n:=0; n < len(scIds)/10 + 1; n++ {
		x := (n+1)*10
		if x > len(scIds) {
			x = len(scIds)
		}
		rects_, err := (&Records{}).RecordTime_(uid, sid, scIds[n*10:x])
		if err != nil {
			return err
		}
		rects = append(rects,rects_...)
	}

	for n, _ := range rects {
		mapps[rects[n].Id].Rect = []RecordAt{rects[n]}
	}
	if err == nil {
		for i, row := range list {
			//var rec Records
			//fmt.Println(uid, row.Id, row.SSId)
			//list[i].Rect, _ = rec.RecordTime(uid, row.Id, row.SSId)
			list[i].IsColl = 2
			for _, v := range collenList {
				if v.SId == row.PlayClass.Id && v.Type == 1 {
					list[i].IsColl = 1
				}
			}

		}
		val.List = list
	}
	return err

}

type RecordAt struct {
	Id        int64  `json:"-" xorm:"cc_id"`
	LectureAt int64  `json:"lecture_at" xorm:"lecture_at"`
	TotalAt   string `json:"total_at" xorm:"total_at"`
}

func (this *Records) RecordTime(uid, id, sid int64) ([]RecordAt, error) {
	swhere := fmt.Sprintf("uid = %d and cc_id = %d and s_id =  %d", uid, id, sid)
	list := make([]RecordAt, 0)
	return list, Db(0).Table("record").Cols("lecture_at,total_at").Where(swhere).Desc("at").Limit(1).Find(&list)
}
func (this *Records) RecordTime_(uid, sid int64, scIds []int64) ([]RecordAt, error) {
	list := []RecordAt{} // C++ new
	err := Db(0).Table("record").Cols("cc_id, lecture_at,total_at").
		Where(fmt.Sprintf("uid = %d and s_id =  %d", uid, sid)).
		In("cc_id", scIds).And("sign = 1").Find(&list)
	return list, err
}

type NewPlayOrdered struct {
	PlayClass `xorm:"extends"`
	SName     []QSName  `json:"s_name" xorm:"-"`  //课程名称
	SSName    []QSSName `json:"ss_name" xorm:"-"` //科目名称
}

func (this *NewPlayOrdered) OpenClassT(val *Pager) error {
	list := make([]NewPlayOrdered, 0)
	val.TName = "playclass"
	val.Page--
	var field, sort string
	switch val.Coll {
	case 0:
		field = fmt.Sprintf("%s.sort", val.TName) // 排序
	default:
		field = fmt.Sprintf("%s.sort", val.TName) // 排序
	}
	if 1 == val.Rules {
		sort = fmt.Sprintf("%s asc", field)
	} else {
		sort = fmt.Sprintf("%s desc", field)
	}

	val.Total, _ = Db(0).Table(val.TName).Where(val.ToWhere()).Count(this)
	err := Db(0).Table(val.TName).
		Where(val.ToWhere()).
		OrderBy(sort).
		Limit(val.Count, val.Page*val.Count).
		Find(&list)
	if err == nil {
		val.List = list
		for i, row := range list {
			var sus Subjects
			list[i].SName, _ = sus.RecordClassName(row.SSId)
			list[i].SSName, _ = sus.RecordClassNName(row.SSId)
		}
		val.List = list
	}
	return err
}

//func (this *PlayClass) NewAudition(sid int64) ([]PlayClass, error) {
//	list := make([]PlayClass, 0)
//	swhere := fmt.Sprintf("sid > %d and sid < %d and audition = 2  ", sid, sid+100000)
//	err := Db(1).Where(swhere).Find(&list)
//	return list, err
//}

//修改禁用课程不可展示
func (this *PlayClass) NewAudition(sid int64) ([]PlayClass,error){
	list := make([]PlayClass,0)
	swhere := fmt.Sprintf("sid > %d and sid < %d and audition = 2  and s.start = 0 ", sid, sid+100000)
	err := Db(1).Table("playclass").
		Join("LEFT","subject as s",fmt.Sprintf("s.id = playclass.sid")).
		Where(swhere).
		Find(&list)
	return list,err
}

func (this *PlayClass) GetAllAudition() ([]PlayClass, error) {
	list := make([]PlayClass, 0)
	err := Db(1).Where("audition = 2 and pid=?", this.PPId).Find(&list)
	return list, err
}

func (this *PlayClass) GetListByIds(ids []int64) ([]PlayClass, error) {
	list := make([]PlayClass, 0)
	err := Db(1).In("id", ids).Find(&list)
	return list, err
}

type NewPlayAudition struct {
	PlayClass `xorm:"extends"`
	SSName    []QSSName `json:"ss_name" xorm:"-"` //科目名称
}

func (this *NewPlayAudition) PlayNewAudition(sid int64, val *Pager) error {
	list := make([]NewPlayAudition, 0)
	swhere := fmt.Sprintf("sid < %d", sid+100000)
	val.TName = "playclass"
	val.Total, _ = Db(0).Table(val.TName).Where(val.ToWhere()).Where(swhere).Count(this)
	err := Db(1).Table(val.TName).Where(val.ToWhere()).Where(swhere).Find(&list)
	if err == nil {
		val.List = list
		for i, row := range list {
			var sus Subjects
			list[i].SSName, _ = sus.RecordClassNName(row.SSId)
		}
		val.List = list
	}
	return err
}
